import hashlib
import os
import random
import re
import string
import uuid
import jwt
import redis
import requests
from PIL import Image
from PIL import ImageDraw
# 导入models类
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
# 导入Q,F
from django.db import connection
from django.db.models import Q
from django.shortcuts import redirect
from django.shortcuts import render, HttpResponse  # 引入HttpResponse
from django.template import loader
from django.views import View
from rest_framework.response import Response
from rest_framework.views import APIView

from mydjango.view import dictfetchall
from userapp.tasks import *
# 建立redis连接
r = redis.Redis(host=settings.redis_host, port=settings.redis_port, password=settings.redis_password)
from mydjango.settings import UPLOAD_ROOT
from .ser import *
from .models import *

import time
import base64
from hashlib import sha256
import hmac
import urllib
import json

#获取用户类别
class GetUserInfo(APIView):
    def get(self,request):

        #获取参数
        id = request.GET.get('id')
        # print('*'*50)
        # print(id)
        #查询
        user = User.objects.filter(id=id).first()
        #序列化
        user_ser = UserSer(user)
        return Response(user_ser.data)

#获取课程类别
class GetCourseType(APIView):
    def get(self,request):

        coursetype = CourseType.objects.all()
        #序列化
        coursetype_ser = CoursTypeSer(coursetype,many=True)

        return Response(coursetype_ser.data)

#获取课程类别
class GetCourseTag(APIView):
    def get(self,request):

        coursetags = CourseTags.objects.all()
        #序列化
        coursetags_ser = CourseTagsSer(coursetags,many=True)

        return Response(coursetags_ser.data)

#课程详情信息
class CourseInfo(APIView):
    def get(self,request):
        cid = request.GET.get('id')
        uid = request.GET.get('uid')
        #查询数据
        course = Course.objects.filter(id=cid).first()
        res = {}
        #序列化
        course_ser = CourseSer(course)
        if r.get('u'+str(uid)+'c'+str(cid)):
            res['redflow'] = '已关注'
        
        res['data'] = course_ser.data
        return Response(res)

    def post(self,request):
        type = int(request.data.get('type'))
        cid = request.data.get('id')
        uid = request.data.get('uid')
        
        if type == 0:
            #查询数据
            course = Course.objects.filter(id=cid).first()
            course.flow += 1
            course.save()

            #关注表存入redis中
            r.set('u'+str(uid)+'c'+str(cid),'1')
            res = {}
            res['code'] = 200
            res['message'] = '关注成功'


            return Response(res)

        if type == 1:
            #查询数据
            course = Course.objects.filter(id=cid).first()
            course.flow -= 1
            course.save()

            #关注表存入redis中
            r.delete('u'+str(uid)+'c'+str(cid))
            res = {}
            res['code'] = 200
            res['message'] = '取关成功'
            return Response(res)

#获取课程信息
class GetCourse(APIView):
    def get(self,request):
        coursetype = int(request.GET.get('coursetype'))
        course_type = request.GET.get('course_type')
        course_tag = request.GET.get('course_tag')
        print(course_type)
        print(course_tag)
        print(coursetype)
        if coursetype == 0:
            #当前页
            page = int(request.GET.get('page',1))
            #一页有几条数据
            size = int(request.GET.get('size',2))

            #定义 从哪里开始切  当前页数-1 乘 一页几条数据
            data_start = (page-1) *size
            #定义 切到哪里
            data_end = page * size

            #查询数据
            course = Course.objects.all()[data_start:data_end]
            print(course)
            #查询总数量
            count = Course.objects.count()
            

            #序列化
            course_ser = CourseSer(course,many=True)
            res = {}
            res['total'] = count
            res['data'] = course_ser.data
            return Response(res)
        elif coursetype == 1:
            
            #查询 课程类别 在其表中所代表的id
            ctype = CourseType.objects.filter(typename=course_type).first()
            #查询 课程标签 在其表中 所代表的id
            ctag = CourseTags.objects.filter(course_tags=course_tag).first()
      
            if ctype and ctag:
                #查询数据
                course = Course.objects.filter(type=ctype.id,tags_id=ctag.id)   

                course_ser = CourseSer(course,many=True)
                res = {}
               
                res['data'] = course_ser.data
                return Response(res)
                
            elif ctype:

                #查询数据
                course = Course.objects.filter(type=ctype.id)   

                course_ser = CourseSer(course,many=True)
                res = {}
             
                res['data'] = course_ser.data
                return Response(res)

            elif ctag:
                #查询数据
                course = Course.objects.filter(tags_id=ctag.id)   
                course_ser = CourseSer(course,many=True)
                res = {}
             
                res['data'] = course_ser.data
                return Response(res)
            


# 用户的修改
class ChangeWeb(APIView):
    # 用户信息
    def get(self, request):
        uid = request.data.get('uid')

        uid = request.GET.get('uid')

        # 查询数据
        user = User.objects.get(id=int(uid))

        # 序列化对象
        user_ser = UserSer(user)

        return Response(user_ser.data)

    # 修改用户信息
    def post(self, request):
        type = int(request.data.get('type'))
        username = request.data.get('username')
        newpassword = request.data.get('newpassword')
        password = request.data.get('password')
        img = request.data.get('img')
        uid = request.data.get('uid')

        # 修改昵称
        if type == 0:
            user = User.objects.filter(id=uid).first()

            user.username = username
            user.save()

            res = {}
            res['code'] = 200
            res['message'] = '修改昵称成功'
            res['username'] = user.username

            return Response(res)
        elif type == 1:
            user = User.objects.filter(id=uid, password=make_password(password)).first()
            if user:

                user.password = make_password(newpassword)
                user.save()
                res = {}
                res['code'] = 200
                res['message'] = '修改密码成功'
                return Response(res)
            else:
                res = {}
                res['code'] = 405
                res['message'] = '原密码输入不正确'
                return Response(res)
        else:

            user = User.objects.filter(id=uid).first()
            user.img = img
            user.save()
            res = {}
            res['code'] = 200
            res['message'] = '修改头像成功'

            return Response(res)


# 定义上传视图类
class UploadFile(View):

    def post(self, request):
        # 接收参数
        img = request.FILES.get('file')
        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '', str(img.name).replace('"', '')), 'wb')

        # 写入服务器端
        for chunk in img.chunks():
            f.write(chunk)
        f.close()
        if img.name.split('.')[-1] != 'mp4':
            # 打开图片
            im = Image.open("./static/upload/" + img.name)

            # 生成画笔对象
            draw = ImageDraw.Draw(im)
            # 修改图片
            draw.text((0, 0), '1906', fill=(0, 0, 255, 0))

            # 存储图片
            im.save('./static/upload/' + img.name)
        return HttpResponse(json.dumps({'filename': str(img.name).replace('"', '')}, ensure_ascii=False
                                       ), content_type='application/json')


class Index(View):
    def get(self, request):
        return HttpResponse("你好，这里是用户app首页。")


class EmailView(APIView):
    # 测试celery
    def get(self, request):
        add.delay(18, 22)
        # send_email.delay()
        return Response({"code": '200'})


class AdminRegView(APIView):
    def post(self, request):
        username = request.data.get("administrator_name")
        password = request.data.get("administrator_pwd")
        user_email = request.data.get("administrator_email")
        # 后台验证邮箱格式
        if not re.match(r'^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){0,4}@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){0,4}$', user_email):
            resp = {}
            resp["code"] = 405
            resp["message"] = '邮箱格式错误'
            return Response(resp)
        # 后台验证密码格式
        if len(password) < 6:
            resp = {}
            resp["code"] = 405
            resp["message"] = '密码格式错误'
            return Response(resp)

        # 管理员排重
        user = User.objects.filter(Q(username=username) | Q(email=user_email)).first()
        resp = {}
        if user:
            resp["code"] = 405
            resp["message"] = '用户已被注册'
            return Response(resp)
        else:
            # 管理员信息入库
            user = User.objects.create(username=username, password=make_password(password), email=user_email, type=0)
            user.save()
            token = uuid.uuid1().hex  # 生成一个随机的字符串
            r.expire(token, 600)  # 设置验证码10min内有效
            # 把一个网页文件 转成 字符串
            html_message = loader.render_to_string("active.html", {"username": user.username, "token": token}, request)
            send_email.delay(user_email, html_message)
            # # 注册成功
            resp["code"] = 200
            resp['message'] = '您已成功注册，请尽快进行邮箱激活'
            return Response(resp)


def active_user(request):
    token = request.GET.get("token")
    username = request.GET.get("username")
    token2 = r.ttl(token)
    if token2 != -1:
        # 激活用户
        user = User.objects.filter(username=username).first()
        if user:
            user.is_active = 1  # 激活
            user.save()  # 保存到数据库
        else:
            # 找不到该用户 请重新注册
            pass
    else:
        # 激活码失效，请重新发送邮件
        return render(request, "active_fail.html")
    return HttpResponse("激活成功")


# 用户登录接口

# 获取JWT
def Verify_JWT(userid):
    encode_jwt = jwt.encode({'uid': str(userid)}, settings.SECRET_KEY, algorithm='HS256')
    # print(encode_jwt)
    return encode_jwt


# 验证JWT
def Encode_JWT(token):
    encode_str = str(token, 'utf-8')
    encode_jwt = jwt.encode(encode_str, settings.SECRET_KEY, algorithm=['HS256'])
    # print(encode_jwt)
    return encode_jwt


# 用户登录接口

class UserLogin(APIView):
    # 使用post请求
    def post(self, request):
        # 获取前端参数
        username = str(request.data.get("username", None))
        password = str(request.data.get("password", None))

        # 打印查看是否成功获取数据
        print({"username": username, "password": password})

        dict_u = {"key": username}
        # print(dict_u)
        # MD5加密
        user = User.objects.filter((Q(username=dict_u['key']) | Q(phone=dict_u['key']) | Q(email=dict_u['key'])),
                                   password=make_password(password)).first()
        user_id = user.id
        # print(user_id)

        token = Verify_JWT(user_id)

        if user:
            res = {}
            res['code'] = 200
            res['message'] = "恭喜您,登陆成功"
            res['username'] = username
            res['uid'] = user.id
            res['token'] = token

            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = ",抱歉,您输入的用户名或密码有误,请查证后重新输入"

            return Response(res)


def make_password(mypass):
    # 生成md5
    md5 = hashlib.md5()
    # 生成加密对象
    mypass_str = mypass
    # 转码
    sign_utf8 = str(mypass_str).encode(encoding='utf-8')
    # 加密
    md5.update(sign_utf8)
    # 生成密文
    md5_server = md5.hexdigest()

    return md5_server


class GetCode(APIView):
    def get(self, request):
        phone = request.GET.get('phone')

        # 声明字符串 区间
        numstr = string.digits
        codestr = "".join(random.sample(numstr, 6))
        code = {'code': codestr}
        # print(codestr)
        # print(code)
        client = AcsClient('LTAI4FyVGc9iJnr28p43mDsh', 'FDNvZuSitpIwFWkmiUMb90q7szZy6H', 'cn-hangzhou')

        request = CommonRequest()
        request.set_accept_format('json')
        request.set_domain('dysmsapi.aliyuncs.com')
        request.set_method('POST')
        request.set_protocol_type('https')  # https | http
        request.set_version('2017-05-25')
        request.set_action_name('SendSms')

        request.add_query_param('RegionId', "cn-hangzhou")
        request.add_query_param('PhoneNumbers', phone)
        request.add_query_param('SignName', "热得快卖得好商城")
        request.add_query_param('TemplateCode', "SMS_188632345")
        request.add_query_param('TemplateParam', code)

        response = client.do_action(request)
        # print(str(response, encoding = 'utf-8'))

        r.set('phonecode', codestr)
        r.expire('phonecode', 300)

        return Response({'phone': phone,'message':'获取验证码成功，五分钟内有效！'})


class Reg(APIView):

    def post(self, request):

        username = request.data.get('username')
        password = request.data.get('password')
        phone = request.data.get('phone')
        web_code = request.data.get('phone_code')

        # print(web_code)
        if r.get('phonecode'):
            phonecode = str(r.get('phonecode'), encoding='utf8')
            if web_code != phonecode:
                res = {}
                res['code'] = 405
                res['message'] = '验证码不正确'
                return Response(res)
            else:
                # 排重
                user = User.objects.filter(username=username).first()
                if user:
                    res = {}
                    res['code'] = 405
                    res['message'] = '用户名已存在'
                    return Response(res)
                else:
                    # 入库
                    User(username=username, password=make_password(password), phone=phone).save()
                    res = {}
                    res['code'] = 200
                    res['message'] = '注册成功'
                    return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = '验证码超时'
            return Response(res)


class Admin_login(APIView):
    def get(self, request):
        # 获取前端参数
        username = str(request.GET.get("username", None))
        password = str(request.GET.get("password", None))
        email = str(request.GET.get("email", None))

        # 打印查看是否成功获取数据
        print({"username": username, "password": password, "email": email})

        dict_u = {"key": username}
        print(dict_u)

        # user = User.objects.filter(username=dict_u['key'],password=password).first()

        # MD5加密
        user = User.objects.filter((Q(username=dict_u['key']) | Q(phone=dict_u['key']) | Q(email=dict_u['key'])),
                                   password=make_password(password)).first()

        if user:
            res = {}
            res['code'] = 200
            res['message'] = "恭喜您,登陆成功"
            res['username'] = user.username
            res['uid'] = user.id

            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = ",抱歉,您输入的用户名或密码有误,请查证后重新输入"

            return Response(res)


# 管理员个人信息修改
class Admin_change(APIView):
    def get(self, request):
        # 获取用户uid
        admin_uid = int(request.GET.get('admin_uid', None))

        # 获取前端传递的修改信息
        old_password = request.GET.get('old_password', None)
        password = request.GET.get('password', None)
        n_phone = request.GET.get('n_phone', None)
        email = request.GET.get('email', None)
        web_code = str(request.GET.get('code', None))

        # 使用uid查询数据库内所关联的用户
        user = User.objects.filter(id=admin_uid).first()

        # 判断user结果是否存在,用户身份是否为管理员以及redis中的phonecode是否存在
        if user and user.type == int(0) and user.password == make_password(old_password) and r.get('phonecode'):
            # 将phonecode获取出来并进行转码
            phonecode = str(r.get('phonecode'), encoding='utf8')

            # 验证code是否与redis中的code相同
            if web_code != str(phonecode):
                res = {}
                res['code'] = 405
                res['message'] = '验证码不正确'

                return Response(res)

            else:
                # 对个人信息进行修改
                user.password = make_password(password)
                user.phone = n_phone
                user.email = email
                # 保存修改
                user.save()

                res = {}
                res['code'] = 200
                res['message'] = "验证码判定成功,您的修改已经提交,请稍后查看修改结果"

                return Response(res)

        else:
            res = {}
            res['code'] = 405
            res['message'] = "很抱歉,您的修改并未成功,请重试或更换管理员账号"

            return Response(res)


class UserInfo(APIView):
    # 用户信息展示
    def get(self, request):
        id = request.GET.get("uid")
        user = User.objects.filter(id=id).first()
        type = {1: '普通用户', 2: '会员用户', 3: "超级会员用户"}
        if user:
            res = {
                'code': 200,
                'type': type[user.type],
                'points': user.points,
                'status': user.status,
                'where': user.where,
                'invite': user.code,
                'img': str(user.img),
            }
            return Response(res)
        else:
            res = {
                'code': 405,
                'message': '用户不存在！'
            }
            return Response(res)


class UserList(APIView):
    def get(self, request):
        # 当前页
        page = int(request.GET.get("page", 1))
        # 一页有多少条商品
        size = int(request.GET.get("size", 3))
        # 定义从哪开始切
        data_start = (page - 1) * size
        # 定义切到哪
        data_end = page * size
        # 查询数据
        users = User.objects.filter(Q(type=1) | Q(type=2) | Q(type=3))[data_start:data_end]
        # 查询总数
        count = User.objects.filter(Q(type=1) | Q(type=2) | Q(type=3)).count()
        # 序列化操作
        user_list = UserSer(users, many=True).data
        res = {}
        res['code'] = 200
        res['total'] = count
        res['data'] = user_list
        return Response(res)

    def delete(self, request):
        id = request.data.get('id')
        user = User.objects.filter(id=id).first()
        user.delete()
        res = {}
        res['code'] = 200
        res['msg'] = '删除成功'
        return Response(res)


class More_del(APIView):
    def get(self, request):
        # 批量取关
        ids = request.GET.get("ids", None)
        # 强转
        id_list = eval(ids)

        for i in id_list:
            user = User.objects.filter(id=i).first()
            user.delete()

        message = "批量删除成功"
        return Response({'message': message})


# 钉钉扫码登录
def dingding_back(request):
    code = request.GET.get("code")
    t = time.time()
    timestamp = str(int(round(t * 1000)))
    appSecret = 'XkGExbfGrTFdAFJFof_dzMw-2MmKjAMyIAkKUsop8t7Txj8mimgCg7rFu8JTSHfE'
    # 构造签名
    signature = base64.b64encode(
        hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
    payload = {'tmp_auth_code': str(code)}
    headers = {'Content-Type': 'application/json'}
    res = requests.post(
        'https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey=dingoadzhvqqu2evyeihsd&timestamp='
        + timestamp +
        "&signature="
        + urllib.parse.quote(signature.decode("utf-8")),
        data=json.dumps(payload), headers=headers
    )
    res_dict = json.loads(res.text)
    # print(res_dict)
    mynick = res_dict['user_info']['nick']
    user = User.objects.filter(username=mynick).first()
    sina_id = ''
    user_id = ''
    if user:
        sina_id = user.username
        user_id = user.id
    else:
        user = User(username=mynick)
        user.save()
        sina_id = mynick
        is_user = User.objects.filter(username=mynick).first()
        user_id = is_user.id
    return redirect("http://localhost:8080/?username=" + sina_id + "&user_id=" + str(user_id))


# 微博扫码登录
def weibo(request):
    #除了刘炎，其他人登录的时候提示{'error': 'applications over the unaudited use restrictions!', 'error_code': 21321, 'request': '/2/users/show.json'}
    # 因为他的微博app没有提交审核，只有他作为开发者可可以登录
    # 获取回调的code
    code = request.GET.get('code')
    # 微博认证地址
    access_token_url = "https://api.weibo.com/oauth2/access_token"
    # 参数
    re_dict = requests.post(access_token_url, data={
        "client_id": '2988843203',
        "client_secret": "55e354c60e2d0c3026e23fdc8dba3ffd",
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": "http://127.0.0.1:8000/user/weibo/",
    }).text
    res = json.loads(re_dict)

    # 获取新浪微博用户名
    result = requests.get(url='https://api.weibo.com/2/users/show.json',
                          params={'access_token': res['access_token'], 'uid': res['uid']})
    result = json.loads(result.text)
    print(result)

    # 判断该用户曾经是否登陆过
    user = User.objects.filter(username=str(result['name'])).first()
    sina_id = ''
    user_id = ''

    if user:
        sina_id = user.username
        user_id = user.id
    else:
        # 手动创建账号
        User.objects.create(username=str(result['name']), password='')
        sina_id = result['name']
        user = User.objects.filter(username=str(result['name'])).first()
        user_id = user.id
    return redirect('http://localhost:8080/?username=' + str(sina_id) + '&user_id=' + str(user_id))

class User_course(View):
    #连表
    def get(self,request):
        # 建立游标对象
        id = request.GET.get('id')
        cursor = connection.cursor()
        # 执行sql语句
        cursor.execute(
            'select c.title,c.id,c.pic,c.flow from course as c inner join user_to_couse as u on c.id = u.course_id where u.uid='+str(id)
                )
        # 获取结果
        # result = cursor.fetchall()
        result = dictfetchall(cursor)
        # 返回结果 手动序列化
        return HttpResponse(json.dumps(result, ensure_ascii=False, indent=4, default=str),
                            content_type='application/json')

class GETUserCourse(APIView):
    def get(self, request):
        uid = request.GET.get("id")
        user_to_course = UsertoCourse.objects.filter(uid=uid)
        utc = UsertoCourseSer(user_to_course,many=True).data
        # print(utc)
        res = {}
        res['code'] = 200
        res['data'] = utc
        return Response(res)


class Is_True(APIView):
    def get(self,request):
        # 获取参数
        uid = request.GET.get('uid')
        course_id = request.GET.get('course_id')
        print(uid,course_id)
        # 查询
        true = UsertoCourse.objects.filter(uid=uid,course_id=course_id).first()
        res = {}
        if true:
            res['code']=200
            res['mode'] = 200
            return Response(res)
        else:
            res['code'] = 500
            res['mode']=500
            return Response(res)

class User_path(View):
    # 连表
    def get(self,request):
        # 建立游标对象
        id = request.GET.get('id')
        cursor = connection.cursor()
        # 执行sql语句
        cursor.execute(
            'select p.path,p.id,p.img,p.course_num,p.desc  from path as p inner join user_to_path as u on p.id = u.path_id where u.uid='+str(id)
                )
        # 获取结果
        # result = cursor.fetchall()
        result = dictfetchall(cursor)
        # 返回结果 手动序列化
        return HttpResponse(json.dumps(result, ensure_ascii=False, indent=4, default=str),
                            content_type='application/json')


class GETUserPath(APIView):
    def get(self, request):
        uid = request.GET.get("id")
        user_to_course = UsertoPath.objects.filter(uid=uid)
        utp = UsertoPathSer(user_to_course,many=True).data
        res = {}
        res['code'] = 200
        res['data'] = utp
        return Response(res)


# 用户优惠券
class UserCouponsInfo(APIView):
    def get(self, request):
        uid = request.GET.get('uid')
        desclist = []
        # 查询用户是否有优惠券
        couponsto = CouponstoUser.objects.filter(uid=uid)
        if couponsto:
            for i in couponsto:
                coupons = Coupons.objects.filter(id=i.code_id).first()
                # 序列化
                coupons_ser = CouponsSer(coupons).data
                desclist.append(coupons_ser)

        return Response(desclist)

    def post(self, request):

        code_id = request.data.get('code_id')
        uid = request.data.get('uid')

        # 排重
        couponsto = CouponstoUser.objects.filter(code_id=code_id, uid=uid).first()
        if couponsto:
            res = {}
            res['code'] = 405
            res['message'] = '您已拥有此优惠券'
            return Response(res)
        # 入库
        CouponstoUser(code_id=code_id, uid=uid).save()
        res = {}
        res['code'] = 200
        res['message'] = '领取成功'
        return Response(res)


# 优惠券
class CouponsInfo(APIView):
    # 获取优惠券
    def get(self, request):
        coupons = Coupons.objects.all()
        # 序列化
        coupons_ser = CouponsSer(coupons, many=True)

        return Response(coupons_ser.data)